"""
User Manager Module
===================

This module implements the UserManager class, which is responsible for managing all user-related
operations in the GT-LMS system. It follows the Singleton pattern to ensure only one instance
of the user manager exists throughout the application.

The UserManager handles:
- User creation, retrieval, updating, and deletion
- User authentication and password verification
- User data persistence using JSON files
- User search and filtering by role
- User statistics and reporting

主要功能：
- 用户创建、获取、更新和删除
- 用户认证和密码验证
- 使用JSON文件进行用户数据持久化
- 按角色搜索和过滤用户
- 用户统计和报告
"""

import json
import os
from typing import Dict, List, Optional, Any
from datetime import datetime

from gt_lms.models.user import User, Student, Teacher, Admin


class UserManager:
    """
    User Manager - Singleton class for managing all user operations
    
    This class implements the Singleton pattern to ensure only one instance exists.
    It handles all user-related operations including CRUD operations, authentication,
    data persistence, and user management utilities.
    
    用户管理器 - 管理所有用户操作的单例类
    
    该类实现了单例模式，确保只存在一个实例。它处理所有与用户相关的操作，
    包括CRUD操作、身份验证、数据持久化和用户管理工具。
    """
    
    _instance = None  # Singleton instance
    _initialized = False  # Initialization flag
    
    def __new__(cls):
        """
        创建UserManager的单例实例
        
        Returns:
            UserManager: UserManager的单例实例
        """
        if cls._instance is None:
            cls._instance = super(UserManager, cls).__new__(cls)
        return cls._instance
    
    def __init__(self):
        """
        Initialize UserManager instance
        
        初始化用户管理器实例
        
        This method initializes the UserManager with default values and loads
        existing user data from the data file if it exists.
        
        此方法使用默认值初始化用户管理器，并从数据文件加载现有用户数据（如果存在）。
        """
        # Prevent re-initialization of singleton instance
        # 防止单例实例重新初始化
        if self._initialized:
            return
            
        # User storage dictionary - stores all users by user_id
        # 用户存储字典 - 按user_id存储所有用户
        self.users: Dict[str, User] = {}
        
        # Users by role - categorizes users by their role for efficient lookup
        # 按角色分类的用户 - 按角色分类用户以便高效查找
        self.users_by_role: Dict[str, List[str]] = {
            'student': [],
            'teacher': [],
            'admin': []
        }
        
        # Data file path - location where user data is persisted
        # 数据文件路径 - 用户数据持久化的位置
        self.data_file = os.path.join(os.path.dirname(__file__), '..', 'data', 'users.json')
        
        # Load existing user data
        # 加载现有用户数据
        self._load_users()
        
        # Mark as initialized
        # 标记为已初始化
        self._initialized = True
    
    def _load_users(self) -> None:
        """
        Load user data from JSON file
        
        从JSON文件加载用户数据
        
        This method loads user data from the data file if it exists. It deserializes
        the JSON data and reconstructs user objects with their respective types.
        
        如果数据文件存在，此方法会从数据文件加载用户数据。它反序列化JSON数据并重建具有各自类型的用户对象。
        
        Note:
            - If the data file doesn't exist, it initializes with empty user collections
            - If there's an error reading the file, it prints an error message
            - 注意：如果数据文件不存在，则使用空用户集合初始化；如果读取文件时出错，则打印错误消息
        """
        try:
            # Check if data file exists
            # 检查数据文件是否存在
            if os.path.exists(self.data_file):
                # Read and parse JSON data
                # 读取并解析JSON数据
                with open(self.data_file, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                
                # Process each user in the data
                # 处理数据中的每个用户
                for user_id, user_data in data.items():
                    # Deserialize user data to create user object
                    # 反序列化用户数据以创建用户对象
                    user = self._deserialize_user(user_data)
                    if user:
                        # Add user to collections
                        # 将用户添加到集合中
                        self.users[user_id] = user
                        self.users_by_role[user.role].append(user_id)
            else:
                # If data file doesn't exist, initialize with empty collections
                # 如果数据文件不存在，则使用空集合初始化
                self.users = {}
                self.users_by_role = {
                    'student': [],
                    'teacher': [],
                    'admin': []
                }
        except Exception as e:
            # Handle errors during file reading or parsing
            # 处理文件读取或解析过程中的错误
            print(f"Error loading user data: {e}")
            # Initialize with empty collections on error
            # 出错时使用空集合初始化
            self.users = {}
            self.users_by_role = {
                'student': [],
                'teacher': [],
                'admin': []
            }
    
    def _save_users(self) -> None:
        """
        Save user data to JSON file
        
        将用户数据保存到JSON文件
        
        This method serializes all user objects and saves them to the data file.
        It ensures data persistence across application sessions.
        
        此方法序列化所有用户对象并将其保存到数据文件中。它确保跨应用程序会话的数据持久性。
        
        Note:
            - Creates the data directory if it doesn't exist
            - Handles errors during file writing
            - 注意：如果数据目录不存在则创建它；处理文件写入过程中的错误
        """
        try:
            # Create data directory if it doesn't exist
            # 如果数据目录不存在则创建它
            os.makedirs(os.path.dirname(self.data_file), exist_ok=True)
            
            # Serialize all users
            # 序列化所有用户
            data = {}
            for user_id, user in self.users.items():
                data[user_id] = self._serialize_user(user)
            
            # Write data to file
            # 将数据写入文件
            with open(self.data_file, 'w', encoding='utf-8') as f:
                json.dump(data, f, indent=2, ensure_ascii=False, default=str)
        except Exception as e:
            # Handle errors during file writing
            # 处理文件写入过程中的错误
            print(f"Error saving user data: {e}")
    
    def _serialize_user(self, user: User) -> Dict[str, Any]:
        """
        Serialize user object to dictionary for JSON storage
        
        将用户对象序列化为字典以进行JSON存储
        
        This method converts a user object into a dictionary representation that
        can be easily stored in JSON format. It handles different user types and
        preserves all relevant user attributes.
        
        此方法将用户对象转换为可以轻松存储在JSON格式中的字典表示。它处理不同类型的用户并保留所有相关的用户属性。
        
        Args:
            user (User): User object to serialize
                         要序列化的用户对象
            
        Returns:
            Dict[str, Any]: Dictionary representation of the user
                            用户的字典表示
        """
        # Common user attributes
        # 通用用户属性
        data = {
            'user_id': user.user_id,
            'name': user.name,
            'email': user.email,
            '_password': user._password,  # Store hashed password
            'role': user.role,
            'created_at': user.created_at.isoformat() if user.created_at else None,
            'last_login': user.last_login.isoformat() if user.last_login else None,
            'is_active': user.is_active
        }
        
        # Role-specific attributes
        # 角色特定属性
        if isinstance(user, Student):
            data.update({
                'student_number': user.student_number,
                'major': user.major,
                'enrolled_courses': user.enrolled_courses
            })
        elif isinstance(user, Teacher):
            data.update({
                'employee_id': user.employee_id,
                'department': user.department,
                'courses_taught': user.courses_taught
            })
        elif isinstance(user, Admin):
            data.update({
                'admin_level': user.admin_level,
                'permissions': user.permissions
            })
        
        return data
    
    def _deserialize_user(self, data: Dict[str, Any]) -> Optional[User]:
        """
        Deserialize user data from dictionary to create user object
        
        将用户数据从字典反序列化以创建用户对象
        
        This method reconstructs a user object from its dictionary representation.
        It handles different user types and properly initializes all user attributes.
        
        此方法从其字典表示重建用户对象。它处理不同类型的用户并正确初始化所有用户属性。
        
        Args:
            data (Dict[str, Any]): Dictionary representation of user data
                                   用户数据的字典表示
            
        Returns:
            Optional[User]: Reconstructed user object, or None if deserialization failed
                            重建的用户对象，如果反序列化失败则返回None
        """
        try:
            # Create user object based on role
            # 根据角色创建用户对象
            user = None
            role = data.get('role', '')
            
            if role == 'student':
                # Create Student object
                # 创建学生对象
                user = Student(
                    user_id=data['user_id'],
                    name=data['name'],
                    email=data['email'],
                    password="",  # Password will be set below
                    student_number=data.get('student_number', ''),
                    major=data.get('major', '')
                )
                # Set student-specific attributes
                # 设置学生特定属性
                user.enrolled_courses = data.get('enrolled_courses', [])
            elif role == 'teacher':
                # Create Teacher object
                # 创建教师对象
                user = Teacher(
                    user_id=data['user_id'],
                    name=data['name'],
                    email=data['email'],
                    password="",  # Password will be set below
                    employee_id=data.get('employee_id', ''),
                    department=data.get('department', '')
                )
                # Set teacher-specific attributes
                # 设置教师特定属性
                user.courses_taught = data.get('courses_taught', [])
            elif role == 'admin':
                # Create Admin object
                # 创建管理员对象
                user = Admin(
                    user_id=data['user_id'],
                    name=data['name'],
                    email=data['email'],
                    password="",  # Password will be set below
                    admin_level=data.get('admin_level', 1)
                )
                # Set admin-specific attributes
                # 设置管理员特定属性
                user.permissions = data.get('permissions', [])
            else:
                # Unknown role, skip
                # 未知角色，跳过
                return None
                
            # Set common attributes
            # 设置通用属性
            user._password = data['_password']  # Set hashed password
            user.created_at = datetime.fromisoformat(data['created_at']) if data.get('created_at') else datetime.now()
            user.last_login = datetime.fromisoformat(data['last_login']) if data.get('last_login') else None
            user.is_active = data.get('is_active', True)
            
            return user
        except Exception as e:
            print(f"Error deserializing user data: {e}")
            return None
    
    def create_user(self, user_type: str, user_info: Dict[str, Any]) -> Optional[str]:
        """
        Create new user
        
        创建新用户
        
        This method creates a new user of the specified type with the provided information.
        It validates required fields, generates a unique user ID, adds the user to the
        system, and saves the updated user data.
        
        此方法使用提供的信息创建指定类型的新用户。它验证必需字段，生成唯一的用户ID，
        将用户添加到系统中，并保存更新后的用户数据。
        
        Args:
            user_type (str): User type ('student', 'teacher', 'admin')
                             用户类型（'student', 'teacher', 'admin'）
            user_info (Dict[str, Any]): User information
                                        用户信息
            
        Returns:
            Optional[str]: User ID, or None if creation failed
                           用户ID，如果创建失败则返回None
            
        Example:
            >>> user_manager = UserManager()
            >>> user_info = {
            ...     'name': 'John Doe',
            ...     'email': 'john@example.com',
            ...     'password': 'password123',
            ...     'student_number': 'S123456',
            ...     'major': 'Computer Science'
            ... }
            >>> user_id = user_manager.create_user('student', user_info)
            >>> print(user_id)
            student_1
        """
        try:
            # Generate user ID
            # 生成用户ID
            user_id = f"{user_type}_{len(self.users) + 1}"
            
            # Check if user ID already exists
            # 检查用户ID是否已存在
            if user_id in self.users:
                # If exists, try to generate new ID
                # 如果存在，尝试生成新ID
                counter = 1
                while f"{user_type}_{len(self.users) + counter}" in self.users:
                    counter += 1
                user_id = f"{user_type}_{len(self.users) + counter}"
            
            # Create user object
            # 创建用户对象
            user = None
            if user_type == 'student':
                required_fields = ['name', 'email', 'password', 'student_number', 'major']
                if not all(field in user_info for field in required_fields):
                    print("Missing required student information fields")
                    return None
                    
                user = Student(
                    user_id=user_id,
                    name=user_info['name'],
                    email=user_info['email'],
                    password=user_info['password'],
                    student_number=user_info['student_number'],
                    major=user_info['major']
                )
            elif user_type == 'teacher':
                required_fields = ['name', 'email', 'password', 'employee_id', 'department']
                if not all(field in user_info for field in required_fields):
                    print("Missing required teacher information fields")
                    return None
                    
                user = Teacher(
                    user_id=user_id,
                    name=user_info['name'],
                    email=user_info['email'],
                    password=user_info['password'],
                    employee_id=user_info['employee_id'],
                    department=user_info['department']
                )
            elif user_type == 'admin':
                required_fields = ['name', 'email', 'password', 'admin_level']
                if not all(field in user_info for field in required_fields):
                    print("Missing required admin information fields")
                    return None
                    
                user = Admin(
                    user_id=user_id,
                    name=user_info['name'],
                    email=user_info['email'],
                    password=user_info['password'],
                    admin_level=user_info['admin_level']
                )
            else:
                print(f"Unsupported user type: {user_type}")
                return None
            
            # Add to user manager
            # 添加到用户管理器
            self.users[user_id] = user
            self.users_by_role[user.role].append(user_id)
            
            # Save to file
            # 保存到文件
            self._save_users()
            
            print(f"Successfully created {user_type} user: {user_id}")
            return user_id
        except Exception as e:
            print(f"Error creating user: {e}")
            return None
    
    def get_user(self, user_id: str) -> Optional[User]:
        """
        Get user object by user ID
        
        通过用户ID获取用户对象
        
        This method retrieves a user object by its unique user ID. It returns None
        if no user with the specified ID exists.
        
        此方法通过唯一的用户ID检索用户对象。如果不存在具有指定ID的用户，则返回None。
        
        Args:
            user_id (str): User ID
                           用户ID
            
        Returns:
            Optional[User]: User object, or None if not found
                            用户对象，如果未找到则返回None
        """
        return self.users.get(user_id)
    
    def update_user(self, user_id: str, update_info: Dict[str, Any]) -> bool:
        """
        Update user information
        
        更新用户信息
        
        This method updates the information of an existing user. It validates that
        the user exists, updates allowed fields, and saves the changes to the data file.
        
        此方法更新现有用户的信息。它验证用户是否存在，更新允许的字段，并将更改保存到数据文件中。
        
        Args:
            user_id (str): User ID
                           用户ID
            update_info (Dict[str, Any]): Update information
                                          更新信息
            
        Returns:
            bool: True if update successful, False otherwise
                  如果更新成功则返回True，否则返回False
        """
        user = self.get_user(user_id)
        if not user:
            print(f"User not found: {user_id}")
            return False
            
        try:
            # Update common fields
            # 更新通用字段
            allowed_fields = ['name', 'email']
            for field in allowed_fields:
                if field in update_info:
                    setattr(user, field, update_info[field])
            
            # Update role-specific fields
            # 更新角色特定字段
            if isinstance(user, Student) and 'major' in update_info:
                user.major = update_info['major']
            elif isinstance(user, Teacher) and 'department' in update_info:
                user.department = update_info['department']
            elif isinstance(user, Admin) and 'admin_level' in update_info:
                user.admin_level = update_info['admin_level']
            
            # Save to file
            # 保存到文件
            self._save_users()
            
            print(f"Successfully updated user: {user_id}")
            return True
        except Exception as e:
            print(f"Error updating user: {e}")
            return False
    
    def delete_user(self, user_id: str) -> bool:
        """
        Delete user
        
        删除用户
        
        This method removes a user from the system. It validates that the user exists,
        removes the user from all collections, and saves the updated user data.
        
        此方法从系统中删除用户。它验证用户是否存在，从所有集合中删除用户，并保存更新后的用户数据。
        
        Args:
            user_id (str): User ID
                           用户ID
            
        Returns:
            bool: True if deletion successful, False otherwise
                  如果删除成功则返回True，否则返回False
        """
        user = self.get_user(user_id)
        if not user:
            print(f"User not found: {user_id}")
            return False
            
        try:
            # Remove from user dictionary
            # 从用户字典中删除
            del self.users[user_id]
            
            # Remove from role classification
            # 从角色分类中删除
            if user_id in self.users_by_role[user.role]:
                self.users_by_role[user.role].remove(user_id)
            
            # Save to file
            # 保存到文件
            self._save_users()
            
            print(f"Successfully deleted user: {user_id}")
            return True
        except Exception as e:
            print(f"Error deleting user: {e}")
            return False
    
    def authenticate_user(self, email: str, password: str) -> Optional[User]:
        """
        Authenticate user credentials
        
        验证用户凭据
        
        This method authenticates a user by email and password. It searches for a user
        with the specified email, verifies the password, and updates the last login time
        if authentication is successful.
        
        此方法通过电子邮件和密码验证用户。它搜索具有指定电子邮件的用户，验证密码，
        如果身份验证成功则更新上次登录时间。
        
        Args:
            email (str): User email
                         用户邮箱
            password (str): User password
                            用户密码
            
        Returns:
            Optional[User]: Authenticated user object, or None if authentication failed
                            经过身份验证的用户对象，如果身份验证失败则返回None
        """
        # Find user with specified email
        # 查找具有指定邮箱的用户
        for user in self.users.values():
            if user.email == email:
                # Verify password
                # 验证密码
                if user.verify_password(password) and user.is_active:
                    user.last_login = datetime.now()
                    self._save_users()
                    return user
                    
        return None
    
    def get_users_by_role(self, role: str) -> List[User]:
        """
        Get user list by role
        
        按角色获取用户列表
        
        This method returns a list of users with the specified role. It filters users
        by role and returns the corresponding user objects.
        
        此方法返回具有指定角色的用户列表。它按角色过滤用户并返回相应的用户对象。
        
        Args:
            role (str): User role ('student', 'teacher', 'admin')
                        用户角色（'student', 'teacher', 'admin'）
            
        Returns:
            List[User]: User list of the specified role
                        指定角色的用户列表
        """
        if role not in self.users_by_role:
            return []
            
        user_list = []
        for user_id in self.users_by_role[role]:
            user = self.get_user(user_id)
            if user:
                user_list.append(user)
        return user_list
    
    def search_users(self, keyword: str) -> List[User]:
        """
        Search users by keyword (name, email, student number, employee ID)
        
        通过关键字搜索用户（姓名、邮箱、学号、工号）
        
        This method searches for users based on a keyword that can match names, emails,
        student numbers (for students), or employee IDs (for teachers).
        
        此方法基于可以匹配姓名、邮箱、学号（学生）或工号（教师）的关键字搜索用户。
        
        Args:
            keyword (str): Search keyword
                           搜索关键字
            
        Returns:
            List[User]: Matching user list
                        匹配的用户列表
        """
        results = []
        keyword_lower = keyword.lower()
        
        for user in self.users.values():
            # Check name and email
            # 检查姓名和邮箱
            if (keyword_lower in user.name.lower() or 
                keyword_lower in user.email.lower()):
                results.append(user)
                continue
                
            # Check student number (for students only)
            # 检查学号（仅限学生）
            if isinstance(user, Student) and keyword_lower in user.student_number.lower():
                results.append(user)
                continue
                
            # Check employee ID (for teachers only)
            # 检查工号（仅限教师）
            if isinstance(user, Teacher) and keyword_lower in user.employee_id.lower():
                results.append(user)
                continue
                
        return results
    
    def get_user_count(self) -> Dict[str, int]:
        """
        Get user count statistics by type
        
        按类型获取用户数量统计
        
        This method returns statistics about the number of users in the system,
        categorized by user type.
        
        此方法返回系统中用户数量的统计信息，按用户类型分类。
        
        Returns:
            Dict[str, int]: User count statistics by type
                            按类型的用户数量统计
        """
        return {
            'total': len(self.users),
            'students': len(self.users_by_role['student']),
            'teachers': len(self.users_by_role['teacher']),
            'admins': len(self.users_by_role['admin'])
        }
    
    def deactivate_user(self, user_id: str) -> bool:
        """
        Deactivate user account
        
        停用用户账户
        
        This method deactivates a user account, preventing the user from logging in
        while preserving their data in the system.
        
        此方法停用用户账户，防止用户登录，同时保留其在系统中的数据。
        
        Args:
            user_id (str): User ID
                           用户ID
            
        Returns:
            bool: True if deactivation successful, False otherwise
                  如果停用成功则返回True，否则返回False
        """
        user = self.get_user(user_id)
        if not user:
            print(f"User not found: {user_id}")
            return False
            
        user.deactivate()
        self._save_users()
        print(f"Successfully deactivated user: {user_id}")
        return True
